/**
 * Copyright (c) 2015-2015 All Rights Reserved.
 */
package com.zbest.zpay.paycore.biz.action.pay;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.zbest.common.lang.enums.BizCode;
import com.zbest.common.lang.exception.ZpayException;
import com.zbest.zpay.paycore.dal.mapper.PayInfoMapper;
import com.zbest.zpay.paycore.dal.mapper.PaySubInfoMapper;
import com.zbest.zpay.paycore.dal.model.PayInfoDO;
import com.zbest.zpay.paycore.dal.model.PaySubInfoDO;
import com.zbest.zpay.paycore.helper.SeqHelper;
import com.zbest.zpay.paycore.model.PayInfoStatus;
import com.zbest.zpay.paycore.model.PaySubInfoStatus;
import com.zbest.zpay.paycore.model.RefundFlag;
import com.zbest.zpay.paycore.model.convert.PayInfoConvert;
import com.zbest.zpay.paycore.model.convert.PaySubInfoConvert;
import com.zbest.zpay.service.paycore.model.PayInfoDTO;
import com.zbest.zpay.service.paycore.model.PaySubInfoDTO;
import com.zbest.zpay.service.paycore.model.PaycoreKeyEnum;
import com.zbest.zpay.shared.process.BaseAction;
import com.zbest.zpay.shared.process.ProcessResult;

/**
 * 初始化充值信息
 * @author hangdahong
 * @version $Id: GenPayInfoAction.java, v 0.1 2015年1月21日 下午3:49:27 hangdahong Exp $
 */
@Service("genPayInfoAction")
public class GenPayInfoAction extends BaseAction {
    private static Logger       logger = LoggerFactory.getLogger(GenPayInfoAction.class);

    @Resource
    @Qualifier("paycoreTransactionTemplate")
    private TransactionTemplate transactionTemplate;

    @Resource
    private PayInfoMapper       payInfoMapper;

    @Resource
    private PaySubInfoMapper    paySubInfoMapper;

    @Resource
    private SeqHelper           seqHelper;

    /** 
     * @see com.zbest.zpay.shared.process.BaseAction#perform(com.zbest.zpay.shared.process.ProcessResult)
     */
    @Override
    public void perform(ProcessResult processResponse) {

        PayInfoDTO payInfo = getValue(PaycoreKeyEnum.PAY_INFO.getCode());

        final PayInfoDO payInfoDO = PayInfoConvert.initPayInfoDO(payInfo);
        payInfoDO.setPayInfoId(seqHelper.genPayInfoId());
        payInfoDO.setRefundFlag(RefundFlag.N.name());
        payInfoDO.setStatus(PayInfoStatus.INITIAL.getCode());

        setValue(PaycoreKeyEnum.PAY_INFO_DO.getCode(), payInfoDO);

        final List<PaySubInfoDO> paySubInfoDOList = buildPaySubInfoList(payInfo,
            payInfoDO.getPayInfoId());

        setValue(PaycoreKeyEnum.PAY_SUB_INFO_DO_LIST.getCode(), paySubInfoDOList);

        //2.生成主单和子单事务中保存

        ZpayException e = transactionTemplate.execute(new TransactionCallback<ZpayException>() {
            public ZpayException doInTransaction(TransactionStatus status) {
                try {
                    payInfoMapper.insert(payInfoDO);
                    paySubInfoMapper.insertBatch(paySubInfoDOList);
                    return null;
                } catch (Exception e) {
                    logger.error("保存初始化支付信息失败payInfoDO=" + payInfoDO, e);
                    status.setRollbackOnly();
                    return new ZpayException(BizCode.SYSTEM_EXCEPTION, e);
                }
            }
        });

        if (e != null) {
            throw e;
        }

    }

    private List<PaySubInfoDO> buildPaySubInfoList(PayInfoDTO payInfo, String payInfoId) {

        List<PaySubInfoDO> list = new ArrayList<PaySubInfoDO>();
        for (PaySubInfoDTO paySubInfoDTO : payInfo.getPaySubInfoDTOList()) {
            PaySubInfoDO paySubInfoDO = PaySubInfoConvert.initPaySubInfoDO(paySubInfoDTO);
            list.add(paySubInfoDO);
            paySubInfoDO.setPayInfoId(payInfoId);
            paySubInfoDO.setPaySubInfoId(seqHelper.genPaySubInfoId());
            paySubInfoDO.setRefundFlag(RefundFlag.N.name());
            paySubInfoDO.setStatus(PaySubInfoStatus.INITIAL.getCode());
        }
        return list;
    }

}
